package com.jushu.storbox.util.identity;

import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;

public class PartStreamMD5Identity extends AbsStreamIdentity {

	private long partStart = 0;
	
	private long partLength = 0;
	
	private long partCount = 0;
	
	private long remainSize;
	
	byte[] tempBuffer = null;
	
	long streamLenght = 0;
	
	public PartStreamMD5Identity(InputStream inputStream, long partStart, long partLength) {
		super(inputStream);
		try {
			streamLenght = inputStream.available();
			initParam(partStart, partLength);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public PartStreamMD5Identity(InputStream inputStream, long partStart, long partLength, IidentityCallback callback) {
		super(inputStream, callback);
		try {
			streamLenght = inputStream.available();
			initParam(partStart, partLength);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void initParam(long partStart, long partLength){
		if(partStart < 0 || partLength < 0 
				|| partStart > streamLenght
				|| partStart > partLength) {
			throw new IllegalArgumentException("argument is invalied");
		}
		initPartParamters(partStart, partLength);
		computeBufferParamter();
	}

	private void initPartParamters(long partStart, long partLength) {
		this.partStart = partStart;
		this.partLength = partLength > streamLenght ? streamLenght : partLength;
	}

	private void computeBufferParamter() {
		remainSize = partLength % BUFFER_SIZE;
		partCount = partLength / BUFFER_SIZE;
	}

	@Override
	protected String doComputeIdentity() throws Exception {

		tempBuffer = new byte[1024 * 64];
		MessageDigest messageDigest = MessageDigest.getInstance("MD5");
		innerStream.skip(partStart);
		
		int len = -1;
		long currentProgress = 0;
		long oldProgress = 0;
		long progress = 0;
		for(long index = 0; index < partCount; index++) {
			len = innerStream.read(tempBuffer, 0, BUFFER_SIZE);
			if(len == -1) {
				break;
			}
			messageDigest.update(tempBuffer, 0, len);
			currentProgress = len;
			oldProgress = currentProgress * 100 / partLength;
			if ( progress != oldProgress) {
				progress = oldProgress;
				IdentityCallback.onProgress((int) progress,
						(long) currentProgress, partLength);
			}
		}
		
		len = innerStream.read(tempBuffer, 0, (int)remainSize);
		if(len > 0) {
			messageDigest.update(tempBuffer, 0, len);
			IdentityCallback.onProgress(100, partLength, partLength);
		}
		identity = bytes2String(messageDigest.digest());
		tempBuffer = null;
		innerStream.reset();
		return identity;
	}

}
